package com.firemoss.atonement.test.changewatcher.observation
{
	import com.firemoss.atonement.changewatcher.observation.ChangeObserver;
	import com.firemoss.atonement.changewatcher.observation.DefaultChangeObserverFactory;
	import com.firemoss.atonement.changewatcher.observation.IChangeObserverFactory;
	import com.firemoss.atonement.changewatcher.observation.PropertyChange;
	import com.firemoss.atonement.changewatcher.observation.PropertyChanges;
	import com.firemoss.atonement.test.metadata.inspectors.bindability.objects.Observer;
	import com.firemoss.atonement.test.metadata.inspectors.bindability.objects.Subject;
	
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.system.System;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.utils.setTimeout;
	
	import mx.events.PropertyChangeEvent;
	
	import org.flexunit.asserts.*;
	import org.flexunit.asserts.assertNull;
	import org.flexunit.async.Async;

	public class ChangeObserverTests
	{		
		private var observerFactory : IChangeObserverFactory = new DefaultChangeObserverFactory();
			
		[Test(async,timeout="500")]
		public function change_observer_should_dispatch_change_events() : void
		{
			var subject : Subject = new Subject();
			subject.property = "foo";
			
			var observer : ChangeObserver = observerFactory.createObserverFor( subject )
				
			var handler : Function = Async.asyncHandler( this, propertyChanged, 500, { target : subject, orig : "foo", delta : "bar" } );
			observer.addEventListener( PropertyChangeEvent.PROPERTY_CHANGE, handler, false, 0, true );
			
			subject.property = "bar";
		}
		
		private function propertyChanged( event : PropertyChangeEvent, data : Object ) : void
		{
			assertTrue( event.source == data.target );
			assertTrue( event.oldValue == data.orig );
			assertTrue( event.newValue == data.delta );
		}

		[Test]
		public function change_observer_should_track_changes_when_told_to() : void
		{
			var subject : Subject = new Subject();
			subject.property = "foo";
			
			var observer : ChangeObserver = observerFactory.createObserverFor( subject )
			
			observer.startTrackingChanges();
			
			subject.property = "foo2";
			subject.property = "bar";
			
			var changeList: Array = observer.getPropertyChangeList();
			
			assertTrue( changeList.length == 2 );
			assertTrue( PropertyChange( changeList[0] ).originalValue = "foo" );
			assertTrue( PropertyChange( changeList[0] ).newValue = "foo2" );
			assertTrue( PropertyChange( changeList[1] ).originalValue = "foo2" );
			assertTrue( PropertyChange( changeList[1] ).newValue = "bar" );
			
			var propertyChanges : PropertyChanges = observer.getPropertyChanges();
			var change : PropertyChange = propertyChanges.forProperty( "property" );
			
			assertTrue( change.originalValue == "foo" );
			assertTrue( change.newValue == "bar" );
			
			changeList = observer.getPropertyChangeList( true );
			changeList = observer.getPropertyChangeList( true );
			assertTrue( changeList.length == 0 );
			
			observer.stopTrackingChanges()
			subject.property = "whee"
			changeList = observer.getPropertyChangeList();
			assertTrue( changeList.length == 0 );
				
			observer.startTrackingChanges()
			subject.property = "whee"
			changeList = observer.getPropertyChangeList();
			assertTrue( changeList.length == 0 );
			subject.property = "whee2"
			changeList = observer.getPropertyChangeList();
			assertTrue( changeList.length == 1 );
			
		}

		[Before]
		public function setUp():void
		{
		}
		
		[After]
		public function tearDown():void
		{
		}
		
		[BeforeClass]
		public static function setUpBeforeClass():void
		{
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
		}
		
		
	}
}